"""
魔法方法使用 + 文件读取 + 自定义异常
设计一个FileReader类, 实现文件读取的功能。要求如下:
1. 初始化方法__init__(self, file_path), 接收一个文件路径作为参数, 并在初始化时判断该目标文件是否存在(os.path模块)
2. 实现上下文管理器方法, 使得该类对象可以在with语句中使用, 确保文件在退出with块后自动关闭
3. 实现__getattr__(self, name), 使得可以通过file_reader.size来获取文件的大小(单位字节)
4. 实现一个读取文件内容的方法read_content(self), 该方法返回文件的全部内容字符串

注: 封装自定义异常,当目标文件/目标属性不存在时，手动抛出异常提示
"""
import os


class MyError(Exception):
    def __init__(self, msg):
        self.msg = msg

    def __str__(self):
        return self.msg


class FileReader(object):
    # 初始化方法，用于调用__new__方法返回实例
    def __init__(self, file_path):
        # 文件路径
        self.file_path = file_path
        # 切片返回文件名
        self.filename = file_path.split('/')[-1]
        # 判断目标文件是否存在
        if not os.path.exists(self.file_path):
            raise MyError(f'目标文件 {self.filename} 不存在！')
        self.file = None
        
    # 资料: https://docs.python.org/zh-cn/3/library/stdtypes.html#contextmanager.__enter__
    def __enter__(self):
        # 打开资源文件
        self.file = open(self.file_path, 'r')
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        # 关闭资源文件
        if self.file:
            self.file.close()
    
    def __getattr__(self, name):
        # 当访问属性为size时进入流程函数返回目标文件大小(字节)
        if name == 'size':
            if self.file:
                """
                seek(offset, whence)
                    offset 偏移量 用于指定相对于whence参数的位置移动了多少个字节
                    whence 可选参数 默认为0
                        0: 从文件开头开始计算偏移量
                        1: 从当前位置开始计算偏移量
                        2: 从文件末尾开始计算偏移量 
                """
                self.file.seek(0, 2)
                # tell() 返回当前指针位置, 即文件大小
                return self.file.tell()
            else:
                raise MyError(f'文件: {self.filename} 读取错误！')
        else:
            raise MyError(f'属性不存在！')
            
    def read_content(self):
        if self.file:
            # 指针重置于文件开头
            self.file.seek(0)
            return self.file.read()
        else:
            return ''


if __name__ == '__main__':
    file_path = f'./../demo_day_07_29/happy.txt'
    
    with FileReader(file_path) as f:
        content = f.read_content()
        print('文件内容: ', content)

        file_size = f.size
        print('文件大小(字节): ', file_size)


"""
伪代码
"""


class MyError(Exception):
    pass


class FileReader(object):
    def __init__(self, file_path):
        pass

    def __enter__(self):
        pass

    def __exit__(self, exc_type, exc_val, exc_tb):
        pass

    def __getattr__(self, name):
        pass

    def read_content(self):
        pass
